.\" Copyright (c) 2009-2020 Julien Nadeau Carriere <vedge@csoft.net>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\"    notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\"    notice, this list of conditions and the following disclaimer in the
.\"    documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
.\" (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd June 15, 2009
.Dt AG_VARIABLE 3
.Os
.ds vT Agar API Reference
.ds oS Agar 1.5.0
.Sh NAME
.Nm AG_Variable
.Nd agar object variables
.Sh SYNOPSIS
.Bd -literal
#include <agar/core.h>
.Ed
.Sh DESCRIPTION
In the Agar object system, each
.Xr AG_Object 3
instance has a set of typed variables.
Variables can be named (accessed by a string key), or anonymous (by pointer).
Basic types include:
.Pp
.Bl -bullet -compact -offset indent
.It
Integers (e.g.,
.Ft int ,
.Ft Uint ,
.Ft long ,
.Ft Sint16 ,
.Ft Uint64 )
.It
Floating-point numbers (e.g.,
.Ft float ,
.Ft double ,
.Ft long double )
.It
Unbounded C strings (auto-allocated)
.It
Generic pointers
.El
.Pp
Typed references (or "pointer variables") are also supported.
Optionally, pointer variables can be configured to acquire a
.Xr AG_Mutex 3
locking device prior to accessing the data.
Reference types include:
.Pp
.Bl -bullet -compact -offset indent
.It
Integers (e.g.,
.Ft int * ,
.Ft long * ,
.Ft Uint * ,
.Ft Sint16 * ,
.Ft Uint64 * )
.It
Floating-point numbers (e.g.,
.Ft float * ,
.Ft double * ,
.Ft long double * )
.It
Bits in a fixed-size word (per given bitmask)
.It
Bounded C strings (in fixed-size buffer)
.It
Agar objects (pointer to
.Xr AG_Object 3 ) .
.It
Proxy for a named
.Nm
in an external
.Xr AG_Object 3
.El
.Pp
Besides representing
.Xr AG_Object 3
instance variables, there are many other uses for
.Nm .
For example, it is also used to represent arguments passed to
.Xr AG_Event 3
callback functions.
In Agar-GUI, widgets use Agar variables to reference data in memory
(also known as "bindings").
For example, the "value" of an
.Xr AG_Numerical 3
spinbutton can be tied to an
.Ft int ,
a
.Ft float
a mutex-protected
.Ft Uint32 ,
etc.
See the "BINDINGS" section of a widget's manual page for the list of bindings
and types supported.
.Sh GENERIC INTERFACE
.nr nS 1
.Ft int
.Fn AG_Defined "AG_Object *obj" "const char *name"
.Pp
.Ft "AG_Variable *"
.Fn AG_GetVariable "AG_Object *obj" "const char *name" "void **data"
.Pp
.Ft "AG_Variable *"
.Fn AG_AccessVariable "AG_Object *obj" "const char *name"
.Pp
.Ft "AG_Variable *"
.Fn AG_FetchVariable "AG_Object *obj" "const char *name" "enum ag_variable_type type"
.Pp
.Ft "AG_Variable *"
.Fn AG_FetchVariableOfType "AG_Object *obj" "const char *name" "enum ag_variable_type type"
.Pp
.Ft void
.Fn AG_LockVariable "AG_Variable *var"
.Pp
.Ft void
.Fn AG_UnlockVariable "AG_Variable *var"
.Pp
.Ft AG_Size
.Fn AG_PrintVariable "char *dst" "AG_Size len" "AG_Variable *var"
.Pp
.Ft void
.Fn AG_CopyVariable "AG_Variable *Vdst" "const AG_Variable *Vsrc"
.Pp
.Ft void
.Fn AG_DerefVariable "AG_Variable *Vdst" "const AG_Variable *Vsrc"
.Pp
.Ft int
.Fn AG_CompareVariables "const AG_Variable *a" "const AG_Variable *b"
.Pp
.Ft "AG_Variable *"
.Fn AG_Set "AG_Object *obj" "const char *name" "const char *fmt" "..."
.Pp
.Ft "void"
.Fn AG_Unset "AG_Object *obj" "const char *name"
.Pp
.Ft void
.Fn AG_VariableSubst "AG_Object *obj" "const char *s" "char *dst" "AG_Size dst_len"
.Pp
.nr nS 0
.Fn AG_Defined
returns 1 if the variable
.Fa name
is defined under the object
.Fa obj ,
otherwise it returns 0.
The object
.Fa obj
must be locked.
.Pp
.Fn AG_GetVariable
searches for a variable
.Fa name
under
.Fa obj
and returns a pointer to the corresponding
.Ft AG_Variable
in a locked condition.
The caller must use
.Fn AG_UnlockVariable
when finished accessing the variable data.
A pointer to the data itself is also returned in the
.Fa data
argument.
If the variable is undefined, a fatal exception is raised.
.Pp
The
.Fn AG_AccessVariable
function searches for a variable by
.Fa name
and returns the matching
.Ft AG_Variable
in a locked condition.
The caller must use
.Fn AG_UnlockVariable
when done accessing the data.
Both
.Fn AG_GetVariable
and
.Fn AG_AccessVariable
return NULL if the named variable is undefined.
.Pp
The
.Fn AG_FetchVariable
function searches for a variable by
.Fa name
and
.Fa type .
If found, return the corresponding
.Ft AG_Variable .
If the variable is undefined then a new one of the specified
.Fa type
is automatically created and returned.
Raises an exception if insufficient memory is available.
.Pp
The
.Fn AG_FetchVariableOfType
variant works like
.Fn AG_FetchVariable ,
except that if the variable exists and is of a different type, then it is
implicitely mutated into
.Fa type
and returned.
.Pp
Note: Unlike
.Fn AG_GetVariable
and
.Fn AG_AccessVariable ,
.Fn AG_FetchVariable
and
.Fn AG_FetchVariableOfType
do not return the
.Ft AG_Variable
locked.
.Pp
.Fn AG_LockVariable
and
.Fn AG_UnlockVariable
acquire and release any locking device associated with the
specified variable.
.Pp
.Fn AG_PrintVariable
generates a string from the value of variable
.Fa var .
The string is written to the fixed-size buffer
.Fa dst
(of size
.Fa len ) .
.Fn AG_PrintVariable
returns the length of the string it tried to create.
.Pp
.Fn AG_CopyVariable
copies the contents of a variable from
.Fa Vsrc
to
.Fa Vdst.
Pointer references are preserved.
Discrete strings are duplicated.
.Pp
.Fn AG_DerefVariable
copies the contents of
.Fa Vsrc
to
.Fa Vdst ,
converting pointer references to immediate values.
Discrete strings are duplicated, and pointers to strings are turned into
discrete strings.
.Pp
The
.Fn AG_CompareVariables
compares the value of two variables, returning zero if they are identical.
If they differ, the difference between the two first differing bytes is
returned.
If
.Fn AG_CompareVariables
encounters pointer types, they are not dereferenced (rather the value of the
pointer itself is compared).
.Pp
The
.Fn AG_Set
sets an object-bound variable value using a format-string interface (see
.Fn AG_PARSE_VARIABLE_ARGS ) .
.Pp
.Fn AG_Unset
deletes the named object-bound variable.
.Pp
.Fn AG_VariableSubst
parses the string
.Fa s
for references of the form "$(foo)", and substitutes those references for
the value of variable
.Va foo
(under object
.Fa obj ) .
The substituted string is returned into fixed-size buffer
.Fa dst ,
of size
.Fa dst_size .
.Sh TYPE-SPECIFIC INTERFACES
The following functions get and set variables of specific types.
.Pp
.Fn AG_Get<Type>
returns the value of variable
.Fa name
under object
.Fa obj
with implicit dereferencing.
If the variable is a pointer type then the value referenced by it is returned.
.Pp
The
.Fn AG_Init<Type>
functions initialize an
.Ft AG_Variable
structure
.Fa var
with the specified value
.Fa val .
.Pp
The
.Fn AG_Set<Type>
functions set the value of variable
.Fa name
to the specified value
.Fa val .
Implicit dereferencing is done.
If the variable does not exist, it is created.
.Pp
The
.Fn AG_Bind<Type>
functions create or modify a typed pointer variable.
The argument
.Fa pVal
is a pointer to the actual value.
.Pp
The
.Fn AG_Bind<Type>Mp
variant accepts an extra
.Fa lock
argument, which is a mutex device (i.e., an
.Ft AG_Mutex
or
.Ft pthread_mutex_t )
to be acquired whenever the data referenced by
.Fa pVal
will be accessed.
.Sh INTEGERS
.nr nS 1
.Ft "Uint"
.Fn AG_GetUint "AG_Object *obj" "const char *name"
.Pp
.Ft "void"
.Fn AG_InitUint "AG_Variable *var" "Uint val"
.Pp
.Ft "AG_Variable *"
.Fn AG_SetUint "AG_Object *obj" "const char *name" "Uint val"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindUint "AG_Object *obj" "const char *name" "Uint *pVal"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindUintMp "AG_Object *obj" "const char *name" "Uint *pVal" "AG_Mutex *lock"
.Pp
.Ft "int"
.Fn AG_GetInt "AG_Object *obj" "const char *name"
.Pp
.Ft "void"
.Fn AG_InitInt "AG_Variable *var" "int val"
.Pp
.Ft "AG_Variable *"
.Fn AG_SetInt "AG_Object *obj" "const char *name" "int val"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindInt "AG_Object *obj" "const char *name" "int *pVal"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindIntMp "AG_Object *obj" "const char *name" "int *pVal" "AG_Mutex *lock"
.Pp
.Ft "Uint8"
.Fn AG_GetUint8 "AG_Object *obj" "const char *name"
.Pp
.Ft "void"
.Fn AG_InitUint8 "AG_Variable *var" "Uint8 val"
.Pp
.Ft "AG_Variable *"
.Fn AG_SetUint8 "AG_Object *obj" "const char *name" "Uint8 val"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindUint8 "AG_Object *obj" "const char *name" "Uint8 *pVal"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindUint8Mp "AG_Object *obj" "const char *name" "Uint8 *pVal" "AG_Mutex *lock"
.Pp
.Ft "Sint8"
.Fn AG_GetSint8 "AG_Object *obj" "const char *name"
.Pp
.Ft "void"
.Fn AG_InitSint8 "AG_Variable *var" "Sint8 val"
.Pp
.Ft "AG_Variable *"
.Fn AG_SetSint8 "AG_Object *obj" "const char *name" "Sint8 val"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindSint8 "AG_Object *obj" "const char *name" "Sint8 *pVal"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindSint8Mp "AG_Object *obj" "const char *name" "Sint8 *pVal" "AG_Mutex *lock"
.Pp
.Ft "Uint16"
.Fn AG_GetUint16 "AG_Object *obj" "const char *name"
.Pp
.Ft "void"
.Fn AG_InitUint16 "AG_Variable *var" "Uint16 val"
.Pp
.Ft "AG_Variable *"
.Fn AG_SetUint16 "AG_Object *obj" "const char *name" "Uint16 val"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindUint16 "AG_Object *obj" "const char *name" "Uint16 *pVal"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindUint16Mp "AG_Object *obj" "const char *name" "Uint16 *pVal" "AG_Mutex *lock"
.Pp
.Ft "Sint16"
.Fn AG_GetSint16 "AG_Object *obj" "const char *name"
.Pp
.Ft "void"
.Fn AG_InitSint16 "AG_Variable *var" "Sint16 val"
.Pp
.Ft "AG_Variable *"
.Fn AG_SetSint16 "AG_Object *obj" "const char *name" "Sint16 val"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindSint16 "AG_Object *obj" "const char *name" "Sint16 *pVal"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindSint16Mp "AG_Object *obj" "const char *name" "Sint16 *pVal" "AG_Mutex *lock"
.Pp
.Ft "Uint32"
.Fn AG_GetUint32 "AG_Object *obj" "const char *name"
.Pp
.Ft "void"
.Fn AG_InitUint32 "AG_Variable *var" "Uint32 val"
.Pp
.Ft "AG_Variable *"
.Fn AG_SetUint32 "AG_Object *obj" "const char *name" "Uint32 val"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindUint32 "AG_Object *obj" "const char *name" "Uint32 *pVal"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindUint32Mp "AG_Object *obj" "const char *name" "Uint32 *pVal" "AG_Mutex *lock"
.Pp
.Ft "Sint32"
.Fn AG_GetSint32 "AG_Object *obj" "const char *name"
.Pp
.Ft "void"
.Fn AG_InitSint32 "AG_Variable *var" "Sint32 val"
.Pp
.Ft "AG_Variable *"
.Fn AG_SetSint32 "AG_Object *obj" "const char *name" "Sint32 val"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindSint32 "AG_Object *obj" "const char *name" "Sint32 *pVal"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindSint32Mp "AG_Object *obj" "const char *name" "Sint32 *pVal" "AG_Mutex *lock"
.Pp
.Ft "Uint64"
.Fn AG_GetUint64 "AG_Object *obj" "const char *name"
.Pp
.Ft "void"
.Fn AG_InitUint64 "AG_Variable *var" "Uint64 val"
.Pp
.Ft "AG_Variable *"
.Fn AG_SetUint64 "AG_Object *obj" "const char *name" "Uint64 val"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindUint64 "AG_Object *obj" "const char *name" "Uint64 *pVal"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindUint64Mp "AG_Object *obj" "const char *name" "Uint64 *pVal" "AG_Mutex *lock"
.Pp
.Ft "Sint64"
.Fn AG_GetSint64 "AG_Object *obj" "const char *name"
.Pp
.Ft "void"
.Fn AG_InitSint64 "AG_Variable *var" "Sint64 val"
.Pp
.Ft "AG_Variable *"
.Fn AG_SetSint64 "AG_Object *obj" "const char *name" "Sint64 val"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindSint64 "AG_Object *obj" "const char *name" "Sint64 *pVal"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindSint64Mp "AG_Object *obj" "const char *name" "Sint64 *pVal" "AG_Mutex *lock"
.Pp
.nr nS 0
These functions provide an interface to both natural and fixed-size
integers.
The
.Ft Uint64
and
.Ft Sint64
types are only available if
.Dv AG_HAVE_64BIT
is defined.
.Sh REAL NUMBERS
.nr nS 1
.Ft "float"
.Fn AG_GetFloat "AG_Object *obj" "const char *name"
.Pp
.Ft "void"
.Fn AG_InitFloat "AG_Variable *var" "float val"
.Pp
.Ft "AG_Variable *"
.Fn AG_SetFloat "AG_Object *obj" "const char *name" "float val"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindFloat "AG_Object *obj" "const char *name" "float *pVal"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindFloatMp "AG_Object *obj" "const char *name" "float *pVal" "AG_Mutex *lock"
.Pp
.Ft "double"
.Fn AG_GetDouble "AG_Object *obj" "const char *name"
.Pp
.Ft "void"
.Fn AG_InitDouble "AG_Variable *var" "double val"
.Pp
.Ft "AG_Variable *"
.Fn AG_SetDouble "AG_Object *obj" "const char *name" "double val"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindDouble "AG_Object *obj" "const char *name" "double *pVal"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindDoubleMp "AG_Object *obj" "const char *name" "double *pVal" "AG_Mutex *lock"
.Pp
.nr nS 0
These functions provide an interface to floating-point numbers.
.Sh C STRINGS
.nr nS 1
.Ft "AG_Size"
.Fn AG_GetString "AG_Object *obj" "const char *name" "char *dst" "AG_Size dst_size"
.Pp
.Ft "char *"
.Fn AG_GetStringDup "AG_Object *obj" "const char *name"
.Pp
.Ft "char *"
.Fn AG_GetStringP "AG_Object *obj" "const char *name"
.Pp
.Ft "void"
.Fn AG_InitString "AG_Variable *var" "const char *s"
.Pp
.Ft "AG_Variable *"
.Fn AG_SetString "AG_Object *obj" "const char *name" "const char *s"
.Pp
.Ft "AG_Variable *"
.Fn AG_SetStringF "AG_Object *obj" "const char *name" "const char *fmt" "..."
.Pp
.Ft "AG_Variable *"
.Fn AG_SetStringNODUP "AG_Object *obj" "const char *name" "const char *s"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindString "AG_Object *obj" "const char *name" "char *s" "AG_Size len"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindStringMp "AG_Object *obj" "const char *name" "char *s" "AG_Size len" "AG_Mutex *lock"
.Pp
.nr nS 0
These functions provide an interface to C strings.
A string variable may contain an unbounded string, or reference an external
fixed-size buffer.
.Pp
.Fn AG_GetString
copies the contents of a string variable to a fixed-size buffer
.Fa dst
of size
.Fa dst_size
and returns the number of bytes that would have been copied were
.Fa dst_size
unlimited.
.Pp
.Fn AG_GetStringDup
returns a newly-allocated copy of the string variable.
If the string cannot be allocated, NULL is returned.
.Pp
The potentially-unsafe
.Fn AG_GetStringP
returns a direct pointer to the buffer containing the string.
It is not free-threaded (so the object must be locked, and calls protected by
.Fn AG_LockVariable ) .
Note that discrete strings set by
.Fn AG_SetString
are safe to access without locking as long as the variable's parent object is
itself locked.
.Pp
.Fn AG_InitString
initializes a
.Ft AG_Variable
structure with the given string, which is copied from
.Fa s .
.Pp
.Fn AG_SetString
sets the value of a string variable (possibly creating a new variable).
The
.Fa s
argument is a C string which will be either duplicated or copied.
If the given variable exists and is a reference to a fixed-size buffer
(i.e., it was generated by a
.Fn AG_BindString
call), then the contents of
.Fa s
are copied to the the referenced buffer.
If the buffer is too small to fit the string, the string is safely truncated.
The
.Fa s
argument may be set to NULL (in which case further
.Fn AG_GetString
calls will also return NULL).
The
.Fn AG_SetStringF
variant accepts a
.Xr printf 3
style format string argument.
.Pp
The potentially-unsafe
.Fn AG_SetStringNODUP
variant accepts a pointer to a dynamically-allocated string buffer which
will be free'd whenever the parent object is destroyed.
.Pp
.Fn AG_BindString
creates or modifies a variable referencing a fixed-size string buffer
.Fa s ,
of size
.Fa len .
.Sh GENERIC POINTERS
.nr nS 1
.Ft "void *"
.Fn AG_GetPointer "AG_Object *obj" "const char *name"
.Pp
.Ft "void"
.Fn AG_InitPointer "AG_Variable *var" "void *val"
.Pp
.Ft "AG_Variable *"
.Fn AG_SetPointer "AG_Object *obj" "const char *name" "void *val"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindPointer "AG_Object *obj" "const char *name" "void **pVal"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindPointerMp "AG_Object *obj" "const char *name" "void **pVal" "AG_Mutex *lock"
.Pp
.nr nS 0
These functions provide an interface to generic pointer types.
.Sh BITS
.nr nS 1
.Ft "AG_Variable *"
.Fn AG_BindFlag "AG_Object *obj" "const char *name" "Uint *pVal" "Uint bitmask"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindFlagMp "AG_Object *obj" "const char *name" "Uint *pVal" "Uint bitmask" "AG_Mutex *lock"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindFlag8 "AG_Object *obj" "const char *name" "Uint8 *pVal" "Uint8 bitmask"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindFlag8Mp "AG_Object *obj" "const char *name" "Uint8 *pVal" "Uint8 bitmask" "AG_Mutex *lock"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindFlag16 "AG_Object *obj" "const char *name" "Uint16 *pVal" "Uint16 bitmask"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindFlag16Mp "AG_Object *obj" "const char *name" "Uint16 *pVal" "Uint16 bitmask" "AG_Mutex *lock"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindFlag32 "AG_Object *obj" "const char *name" "Uint32 *pVal" "Uint32 bitmask"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindFlag32Mp "AG_Object *obj" "const char *name" "Uint32 *pVal" "Uint32 bitmask" "AG_Mutex *lock"
.Pp
.nr nS 0
These functions provide an interface for binding to specific bits in integers.
They follow the standard form, with an extra
.Fa bitmask
argument.
.Sh OBJECT-TO-OBJECT REFERENCES
.nr nS 1
.Ft "AG_Variable *"
.Fn AG_BindObject "AG_Object *obj" "const char *name" "AG_Object *varObj"
.Pp
.Ft "AG_Variable *"
.Fn AG_BindVariable "AG_Object *obj" "const char *name" "AG_Object *varObj" "const char *varKey"
.Pp
.nr nS 0
The
.Fn AG_BindObject
function creates an Object->Object reference and hard dependency to an
external object
.Fa varObj
and return a
.Dv P_OBJECT
type Variable on success.
A hard dependency implies that if both
.Fa obj
and
.Fa varObj
share the same VFS then Agar will not allow
.Fa varObj
to be released from memory (or detached from the VFS) for as long as the
reference exists.
.Pp
The
.Fn AG_BindVariable
function creates an Object->Variable reference to the variable called
.Fa varKey
under an external object
.Fa varObj ,
returning a
.Dv P_VARIABLE
type Variable on success.
Whenever this Variable is accessed, the external object will be locked and a
copy of its variable
.Fa varKey
will be returned implicitely.
Note: Circular references must be avoided.
.Pp
.Fn AG_BindVariable
implicitely creates an anonymous Object->Object reference to
.Fa varObj
(which is also removed implicitely by
.Fn AG_Unset
or
.Xr AG_ObjectFreeVariables 3
when no more Object->Variable references make use of the object).
.Pp
.Fn AG_BindObject
and
.Fn AG_BindVariable
may fail and return NULL.
.Sh STRUCTURE DATA
For the
.Ft AG_Variable
structure:
.Pp
.Bl -tag -compact -width "char name[AG_VARIABLE_NAME_MAX] "
.It Ft char name[AG_VARIABLE_NAME_MAX]
Variable name (or "" = anonymous).
.It Ft AG_VariableType type
Variable type (see <core/variable.h>).
.It Ft AG_Mutex *mutex
Mutex protecting referenced data.
.It Ft union ag_variable_data data
Stored data (see <core/variable.h>).
.El
.Sh SEE ALSO
.Xr AG_Intro 3 ,
.Xr AG_Event 3 ,
.Xr AG_Object 3
.Sh HISTORY
The
.Nm
interface first appeared in Agar 1.3.4.
It replaced the older
.Xr AG_Prop 3
interface, and widget bindings which were previously stored in
.Xr AG_Widget 3
itself.
.Fn AG_GetVariableLocked
was renamed
.Fn AG_AccessVariable
in Agar 1.6.0.
